#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
PyQt6 Modbus模拟器页面
提供Modbus设备模拟功能
"""
import sys

from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGridLayout,
                            QGroupBox, QPushButton, QLabel, QLineEdit, 
                            QComboBox, QRadioButton, QScrollArea,
                            QFrame, QApplication)
from PyQt6.QtCore import pyqtSignal, Qt
from PyQt6.QtGui import QFont

from utils.communication import ModbusSimulatorManager
from gui.components.pyqt6_log_component import PyQt6LogComponent


class ModbusSimulatorPage(QWidget):
    """Modbus模拟器页面类"""
    
    def __init__(self):
        """初始化Modbus模拟器页面"""
        super().__init__()
        self.title = "Modbus模拟器"
        
        # 初始化通信管理器
        self.modbus_simulator_manager = ModbusSimulatorManager(self._simulator_message_callback)
        
        # 初始化界面
        self._init_ui()
    
    def _init_ui(self):
        """初始化UI界面"""
        # 设置主布局
        main_layout = QHBoxLayout(self)
        main_layout.setContentsMargins(15, 15, 15, 15)
        main_layout.setSpacing(15)
        
        # 左侧控制面板
        control_panel = self._create_control_panel()
        main_layout.addWidget(control_panel, 1)
        
        # 右侧日志面板
        log_panel = self._create_log_panel()
        main_layout.addWidget(log_panel, 3)
        
        # 设置整体样式
        self._setup_styles()
    
    def _setup_styles(self):
        """设置界面样式"""
        # 设置字体
        font = QFont("Arial", 10)
        self.setFont(font)
        
        # 为所有GroupBox设置样式
        for group_box in self.findChildren(QGroupBox):
            group_box.setStyleSheet("""
                QGroupBox {
                    font-weight: bold;
                    border: 1px solid gray;
                    border-radius: 5px;
                    margin-top: 1ex;
                }
                QGroupBox::title {
                    subline-offset: -2px;
                    padding: 0 5px;
                }
            """)
    
    def _create_control_panel(self):
        """创建控制面板"""
        # 外层滚动区域
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)

        # 滚动区域的内容部件
        container = QWidget()
        layout = QVBoxLayout(container)
        layout.setSpacing(15)

        # 协议选择组
        protocol_group = QGroupBox("协议选择")
        protocol_layout = QVBoxLayout(protocol_group)
        protocol_layout.setSpacing(8)
        
        self.tcp_radio = QRadioButton("Modbus TCP")
        self.rtu_radio = QRadioButton("Modbus RTU")
        self.tcp_radio.setChecked(True)
        
        # 设置RadioButton样式
        self.tcp_radio.setStyleSheet("""
            QRadioButton {
                spacing: 5px;
            }
            QRadioButton::indicator {
                width: 18px;
                height: 18px;
            }
        """)
        
        self.rtu_radio.setStyleSheet("""
            QRadioButton {
                spacing: 5px;
            }
            QRadioButton::indicator {
                width: 18px;
                height: 18px;
            }
        """)
        

        self.tcp_radio.toggled.connect(self._on_protocol_change)
        self.rtu_radio.toggled.connect(self._on_protocol_change)

        protocol_layout.addWidget(self.tcp_radio)
        protocol_layout.addWidget(self.rtu_radio)

        # 连接配置组
        self.connection_group = QGroupBox("连接配置 (TCP)")
        self.connection_layout = QGridLayout(self.connection_group)
        self.connection_layout.setSpacing(12)
        self.connection_layout.setContentsMargins(10, 15, 10, 15)

        # 创建TCP配置（默认）
        self._create_tcp_config()

        # 设备配置组
        device_group = QGroupBox("设备配置")
        device_layout = QGridLayout(device_group)
        device_layout.setSpacing(12)
        device_layout.setContentsMargins(10, 15, 10, 15)

        device_count_label = QLabel("设备数量:")
        device_count_label.setStyleSheet("QLabel { font-weight: bold; }")
        device_layout.addWidget(device_count_label, 0, 0)
        self.device_count_edit = QLineEdit("1")
        self.device_count_edit.setStyleSheet("""
            QLineEdit {
                padding: 8px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        device_layout.addWidget(self.device_count_edit, 0, 1)

        slave_id_label = QLabel("起始从站ID:")
        slave_id_label.setStyleSheet("QLabel { font-weight: bold; }")
        device_layout.addWidget(slave_id_label, 1, 0)
        self.start_slave_id_edit = QLineEdit("1")
        self.start_slave_id_edit.setStyleSheet("""
            QLineEdit {
                padding: 8px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        device_layout.addWidget(self.start_slave_id_edit, 1, 1)

        # 寄存器配置组
        register_group = QGroupBox("寄存器配置")
        register_layout = QGridLayout(register_group)
        register_layout.setSpacing(12)
        register_layout.setContentsMargins(10, 15, 10, 15)

        start_addr_label = QLabel("起始地址:")
        start_addr_label.setStyleSheet("QLabel { font-weight: bold; }")
        register_layout.addWidget(start_addr_label, 0, 0)
        self.start_address_edit = QLineEdit("0")
        self.start_address_edit.setStyleSheet("""
            QLineEdit {
                padding: 8px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        register_layout.addWidget(self.start_address_edit, 0, 1)

        end_addr_label = QLabel("结束地址:")
        end_addr_label.setStyleSheet("QLabel { font-weight: bold; }")
        register_layout.addWidget(end_addr_label, 1, 0)
        self.end_address_edit = QLineEdit("5")
        self.end_address_edit.setStyleSheet("""
            QLineEdit {
                padding: 8px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        register_layout.addWidget(self.end_address_edit, 1, 1)

        interval_label = QLabel("更新间隔(秒):")
        interval_label.setStyleSheet("QLabel { font-weight: bold; }")
        register_layout.addWidget(interval_label, 2, 0)
        self.update_interval_edit = QLineEdit("2")
        self.update_interval_edit.setStyleSheet("""
            QLineEdit {
                padding: 8px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        register_layout.addWidget(self.update_interval_edit, 2, 1)

        # 添加到主布局
        layout.addWidget(protocol_group)
        layout.addWidget(self.connection_group)
        layout.addWidget(device_group)
        layout.addWidget(register_group)
        layout.addStretch()

        scroll_area.setWidget(container)
        return scroll_area

    def _create_tcp_config(self):
        """创建TCP配置控件"""
        # 清空配置布局
        for i in reversed(range(self.connection_layout.count())):
            widget = self.connection_layout.itemAt(i).widget()
            if widget:
                widget.setParent(None)

        self.connection_group.setTitle("连接配置 (TCP)")

        # IP地址
        ip_label = QLabel("监听IP:")
        ip_label.setStyleSheet("QLabel { font-weight: bold; }")
        self.connection_layout.addWidget(ip_label, 0, 0)
        self.host_edit = QLineEdit("127.0.0.1")
        self.host_edit.setStyleSheet("""
            QLineEdit {
                padding: 8px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        self.connection_layout.addWidget(self.host_edit, 0, 1)

        # 端口
        port_label = QLabel("端口:")
        port_label.setStyleSheet("QLabel { font-weight: bold; }")
        self.connection_layout.addWidget(port_label, 1, 0)
        self.port_edit = QLineEdit("5020")
        self.port_edit.setStyleSheet("""
            QLineEdit {
                padding: 8px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        self.connection_layout.addWidget(self.port_edit, 1, 1)

        # 启动按钮
        self.start_btn = QPushButton("启动模拟器")
        self.start_btn.setStyleSheet("""
            QPushButton {
                background-color: #2196F3;
                color: white;
                border: none;
                padding: 12px;
                border-radius: 4px;
                font-weight: bold;
                font-size: 11px;
            }
            QPushButton:hover {
                background-color: #1976D2;
            }
            QPushButton:pressed {
                background-color: #0D47A1;
            }
        """)
        self.start_btn.clicked.connect(self._start_simulator)
        self.connection_layout.addWidget(self.start_btn, 10, 0, 1, 2)

    def _create_rtu_config(self):
        """创建RTU配置控件"""
        # 清空配置布局
        for i in reversed(range(self.connection_layout.count())):
            widget = self.connection_layout.itemAt(i).widget()
            if widget:
                widget.setParent(None)

        self.connection_group.setTitle("连接配置 (RTU)")

        # 串口
        port_label = QLabel("串口:")
        port_label.setStyleSheet("QLabel { font-weight: bold; }")
        self.connection_layout.addWidget(port_label, 0, 0)
        self.rtu_port_combo = QComboBox()
        self.rtu_port_combo.setStyleSheet("""
            QComboBox {
                padding: 6px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        self.connection_layout.addWidget(self.rtu_port_combo, 0, 1)

        # 波特率
        baudrate_label = QLabel("波特率:")
        baudrate_label.setStyleSheet("QLabel { font-weight: bold; }")
        self.connection_layout.addWidget(baudrate_label, 1, 0)
        self.rtu_baudrate_combo = QComboBox()
        self.rtu_baudrate_combo.addItems(['9600', '19200', '38400', '57600', '115200'])
        self.rtu_baudrate_combo.setCurrentText('9600')
        self.rtu_baudrate_combo.setStyleSheet("""
            QComboBox {
                padding: 6px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        self.connection_layout.addWidget(self.rtu_baudrate_combo, 1, 1)

        # 数据位
        bytesize_label = QLabel("数据位:")
        bytesize_label.setStyleSheet("QLabel { font-weight: bold; }")
        self.connection_layout.addWidget(bytesize_label, 2, 0)
        self.rtu_bytesize_combo = QComboBox()
        self.rtu_bytesize_combo.addItems(['7', '8'])
        self.rtu_bytesize_combo.setCurrentText('8')
        self.rtu_bytesize_combo.setStyleSheet("""
            QComboBox {
                padding: 6px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        self.connection_layout.addWidget(self.rtu_bytesize_combo, 2, 1)

        # 校验位
        parity_label = QLabel("校验位:")
        parity_label.setStyleSheet("QLabel { font-weight: bold; }")
        self.connection_layout.addWidget(parity_label, 3, 0)
        self.rtu_parity_combo = QComboBox()
        self.rtu_parity_combo.addItems(['N', 'E', 'O'])
        self.rtu_parity_combo.setCurrentText('N')
        self.rtu_parity_combo.setStyleSheet("""
            QComboBox {
                padding: 6px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        self.connection_layout.addWidget(self.rtu_parity_combo, 3, 1)

        # 停止位
        stopbits_label = QLabel("停止位:")
        stopbits_label.setStyleSheet("QLabel { font-weight: bold; }")
        self.connection_layout.addWidget(stopbits_label, 4, 0)
        self.rtu_stopbits_combo = QComboBox()
        self.rtu_stopbits_combo.addItems(['1', '2'])
        self.rtu_stopbits_combo.setCurrentText('1')
        self.rtu_stopbits_combo.setStyleSheet("""
            QComboBox {
                padding: 6px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
        """)
        self.connection_layout.addWidget(self.rtu_stopbits_combo, 4, 1)

        # 刷新串口按钮
        refresh_btn = QPushButton("刷新串口")
        refresh_btn.setStyleSheet("""
            QPushButton {
                background-color: #FF9800;
                color: white;
                border: none;
                padding: 8px;
                border-radius: 4px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #F57C00;
            }
            QPushButton:pressed {
                background-color: #EF6C00;
            }
        """)
        refresh_btn.clicked.connect(self._refresh_rtu_ports)
        self.connection_layout.addWidget(refresh_btn, 5, 0, 1, 2)

        # 启动按钮
        self.start_btn = QPushButton("启动模拟器")
        self.start_btn.setStyleSheet("""
            QPushButton {
                background-color: #2196F3;
                color: white;
                border: none;
                padding: 12px;
                border-radius: 4px;
                font-weight: bold;
                font-size: 11px;
            }
            QPushButton:hover {
                background-color: #1976D2;
            }
            QPushButton:pressed {
                background-color: #0D47A1;
            }
        """)
        self.start_btn.clicked.connect(self._start_simulator)
        self.connection_layout.addWidget(self.start_btn, 10, 0, 1, 2)

        # 刷新串口列表
        self._refresh_rtu_ports()

    def _refresh_rtu_ports(self):
        """刷新RTU串口列表"""
        try:
            import serial.tools.list_ports
            ports = [port.device for port in serial.tools.list_ports.comports()]
            self.rtu_port_combo.clear()
            self.rtu_port_combo.addItems(ports)
        except Exception as e:
            self.log_component.log_message(f"刷新RTU串口列表失败: {e}", "ERROR")

    def _create_log_panel(self):
        """创建日志面板"""
        self.log_component = PyQt6LogComponent(self, "模拟器日志", 20)
        return self.log_component

    def _on_protocol_change(self):
        """协议切换事件处理"""
        if self.tcp_radio.isChecked():
            self._create_tcp_config()
        elif self.rtu_radio.isChecked():
            self._create_rtu_config()

    def _start_simulator(self):
        """启动模拟器"""
        try:
            # 获取设备配置
            device_count = int(self.device_count_edit.text())
            start_slave_id = int(self.start_slave_id_edit.text())
            start_address = int(self.start_address_edit.text())
            end_address = int(self.end_address_edit.text())
            update_interval = float(self.update_interval_edit.text())

            if self.tcp_radio.isChecked():
                host = self.host_edit.text().strip()
                port = int(self.port_edit.text().strip())

                if self.modbus_simulator_manager.start_tcp_simulator(
                    host, port, device_count, start_slave_id,
                    start_address, end_address, update_interval):

                    self.start_btn.setText("停止模拟器")
                    self.start_btn.clicked.disconnect()
                    self.start_btn.clicked.connect(self._stop_simulator)
                    self.log_component.log_message(f"启动TCP模拟器成功: {device_count}个设备, 地址{start_address}-{end_address}")
                else:
                    self.log_component.log_message("启动TCP模拟器失败", "ERROR")

            elif self.rtu_radio.isChecked():
                port = self.rtu_port_combo.currentText().strip()
                baudrate = int(self.rtu_baudrate_combo.currentText())
                bytesize = int(self.rtu_bytesize_combo.currentText())
                parity = self.rtu_parity_combo.currentText()
                stopbits = int(self.rtu_stopbits_combo.currentText())

                if not port:
                    self.log_component.log_message("请选择RTU串口", "WARNING")
                    return

                if self.modbus_simulator_manager.start_rtu_simulator(
                    port, baudrate, bytesize, parity, stopbits,
                    device_count, start_slave_id, start_address, end_address, update_interval):

                    self.start_btn.setText("停止模拟器")
                    self.start_btn.clicked.disconnect()
                    self.start_btn.clicked.connect(self._stop_simulator)
                    self.log_component.log_message(f"启动RTU模拟器成功: {device_count}个设备, 地址{start_address}-{end_address}")
                else:
                    self.log_component.log_message("启动RTU模拟器失败", "ERROR")
        except Exception as e:
            self.log_component.log_message(f"启动模拟器失败: {e}", "ERROR")

    def _stop_simulator(self):
        """停止模拟器"""
        try:
            self.modbus_simulator_manager.stop_simulator()
            self.start_btn.setText("启动模拟器")
            self.start_btn.clicked.disconnect()
            self.start_btn.clicked.connect(self._start_simulator)
            self.log_component.log_message("模拟器已停止")
        except Exception as e:
            self.log_component.log_message(f"停止模拟器错误: {e}", "ERROR")
    
    def _simulator_message_callback(self, message: str, level: str = "INFO", msg_type: str = "normal"):
        """模拟器消息回调"""
        self.log_component.log_message(message, level, msg_type)
        

    def on_close(self):
        """页面关闭时的清理"""
        try:
            self.modbus_simulator_manager.shutdown()
        except:
            pass


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = ModbusSimulatorPage()
    window.show()
    sys.exit(app.exec())